package com.njmaomao.gj.pyot.config;

import com.njmaomao.gj.pyot.common.ResponseCode;
import com.njmaomao.gj.pyot.common.XmlUtil;
import com.njmaomao.gj.pyot.common.exception.SystemBizFail;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.*;
import java.util.stream.Collectors;

public final class Bizs {

    public static final  String INPUT_CHARSET = "UTF-8";
    public static final  String SIGN_TYPE = "MD5";
    public static final  String SYSTEM = "PAYMENT";

    private static final Base64.Decoder decoder = Base64.getDecoder();
    private static final Base64.Encoder encoder = Base64.getEncoder();

    private Bizs(){}

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 金额转换，由元转换以分为单位
     *
     * @param txnAmt
     * @return
     */
    public static int convert2FenUnit(double txnAmt) {
        return BigDecimal.valueOf(txnAmt).multiply(BigDecimal.valueOf(100L)).intValue();
    }

    /**
     *
     * @param txnAmt
     * @return
     */
    public static int convert2FenUnit(String txnAmt) {
        return BigDecimal.valueOf(Double.parseDouble(txnAmt)).multiply(BigDecimal.valueOf(100L)).intValue();
    }

    public static String generateNonceStr() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static String spbillCreateIp() {
        return "192.168.2.68";
    }

    public static String getMd5Sign(Object bean, String key) {

        String xml = XmlUtil.objectToXml(bean);
        Map<String, String> map = XmlUtil.xmltoMap(xml);
        return getMd5Sign(map,key);
    }

    public static String getMd5Sign(Map<String,String> data,String key){
        data.remove("sign");
        TreeMap<String, String> treeMap = sortMap(data);
        String collectStr = treeMap.entrySet().stream().map(e -> String.join("=", e.getKey(), e.getValue())).collect(Collectors.joining("&"));
        String preSignStr = collectStr + "&key=" + key;
        return md5(preSignStr, SIGN_TYPE).toUpperCase();//加密后
    }



    private static TreeMap<String, String> sortMap(Map<String, String> map) {
        return map.entrySet().stream()
                .filter(e -> StringUtils.isNotBlank(e.getValue()))
                .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue(),
                        (v1, v2) -> {
                            throw new RuntimeException(String.format("Duplicate key for values %s and %s", v1, v2));
                        },
                        TreeMap::new));
    }

    public static String md5(String str,String signType){
        try {
            MessageDigest sha = MessageDigest.getInstance(signType);
            return byte2hex(sha.digest(str.getBytes(INPUT_CHARSET)));
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException(e);
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException(e);
        }
    }

    private static String byte2hex(byte[] b) {
        StringBuilder sbDes = new StringBuilder();
        String tmp = null;
        for (int i = 0; i < b.length; i++) {
            tmp = (Integer.toHexString(b[i] & 0xFF));
            if (tmp.length() == 1) {
                sbDes.append("0");
            }
            sbDes.append(tmp);
        }
        return sbDes.toString();
    }

    public static String generateTimestamp() {
        return String.valueOf(System.currentTimeMillis() / 1000l);
    }

    public static void checkSign(Map<String, String> bodyMap, String key) {

        String inSign = bodyMap.remove("sign");

        String md5Sign = getMd5Sign(bodyMap, key);

        SystemBizFail.whenIf(!md5Sign.equals(inSign), ResponseCode.PAYTO.INVALID_SIGN);

    }

    /**
     * 解密微信退款通知
     * @param base64Data
     * @param key
     * @return
     * @throws Exception
     */
    public static String decryptWechatRefundNotify(String base64Data, String key) throws Exception {

        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");

        SecretKeySpec secretKeySpec = new SecretKeySpec(Bizs.md5(key, Bizs.SIGN_TYPE).toLowerCase().getBytes(), "AES");

        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);

        return new String(cipher.doFinal(decoder.decode(base64Data)));
    }

    public static double convert2YuanUnit(Integer txnAmt) {
        return BigDecimal.valueOf(txnAmt).divide(BigDecimal.valueOf(100L)).doubleValue();
    }
}
